<?php

namespace app\common\controller;

use think\Response;
use think\Request;

class BasicApi
{

    protected $request;
    /**
     * @var array 前置操作方法列表
     */
    protected $beforeActionList = [];

    protected $responseType = 'json';
    protected $checkRequest = '*';
    protected $header;
    /**
     * 构造方法
     * @access public
     * @param Request $request Request 对象
     */
    public function __construct(Request $request = null)
    {
        $this->request = is_null($request) ? request() : $request;
        // 控制器初始化
        $this->_initialize();
        // 前置操作方法
        if ($this->beforeActionList) {
            foreach ($this->beforeActionList as $method => $options) {
                is_numeric($method) ?
                    $this->beforeAction($options) :
                    $this->beforeAction($method, $options);
            }
        }
    }

    /**
     * 初始化操作
     * @access protected
     */
    protected function _initialize()
    {
        //是否需要验证请求
        if($this->match($this->checkRequest)){
            $this->checkRequestAuth();
        }
    }

    protected function match($arr = [])
    {
        $arr = is_array($arr) ? $arr : explode(',', $arr);
        if (!$arr) {
            return false;
        }
        $arr = array_map('strtolower', $arr);
        if (in_array(strtolower($this->request->action()), $arr) || in_array('*', $arr)) {
            return true;
        }
        return false;
    }


    /**
     * 前置操作
     * @access protected
     * @param  string $method 前置操作方法名
     * @param  array $options 调用参数 ['only'=>[...]] 或者 ['except'=>[...]]
     * @return void
     */
    protected function beforeAction($method, $options = [])
    {
        if (isset($options['only'])) {
            if (is_string($options['only'])) {
                $options['only'] = explode(',', $options['only']);
            }

            if (!in_array($this->request->action(), $options['only'])) {
                return;
            }
        } elseif (isset($options['except'])) {
            if (is_string($options['except'])) {
                $options['except'] = explode(',', $options['except']);
            }

            if (in_array($this->request->action(), $options['except'])) {
                return;
            }
        }

        call_user_func([$this, $method]);
    }

    /**
     * 操作成功返回的数据
     * @param string $msg 提示信息
     * @param mixed $data 要返回的数据
     * @param int $code 错误码，默认为200
     * @param string $type 输出类型
     * @param array $header 发送的 Header 信息
     */
    protected function success($msg = '', $data = null, $code = 200, $type = null, array $header = [])
    {
        $this->result($msg, $data, $code, $type, $header);
    }

    /**
     * 操作失败返回的数据
     * @param string $msg 提示信息
     * @param mixed $data 要返回的数据
     * @param int $code 错误码，默认为400
     * @param string $type 输出类型
     * @param array $header 发送的 Header 信息
     */
    protected function error($msg = '', $data = null, $code = 400, $type = null, array $header = [])
    {
        $this->result($msg, $data, $code, $type, $header);
    }

    /**
     * 返回封装后的 API 数据到客户端
     * @access protected
     * @param mixed $msg 提示信息
     * @param mixed $data 要返回的数据
     * @param int $code 错误码，默认为200
     * @param string $type 输出类型，支持json/xml/jsonp
     * @param array $header 发送的 Header 信息
     * @return void
     */
    protected function result($msg, $data = null, $code = 200, $type = null, array $header = [])
    {
        $result = [
            'code' => $code,
            'msg' => $msg,
            'data' => $data,
        ];
        // 如果未设置类型则自动判断
        $type = $type ? $type : ($this->request->param(config('var_jsonp_handler')) ? 'jsonp' : $this->responseType);
        Response::create($result, $type)->header($header)->send();
        exit;
    }

    /**
     * 检查请求api数据是否合法
     * sign = md5('api_key=API_KEY&platform=wechat_mini&time=TIME&&token=TOKEN')
     * @api_key API秘钥，前后端约定好的一个常量,必填
     * @token 保持会话标识,可空
     * @time 客户端时间戳，,必填
     * @platform 前端应用平台（微信小程序，微信公众号，安卓，IOS）与 baseAuth的子类对应,必填
     */
    protected function checkRequestAuth(){
        $this->header = $this->request->header();
        if (empty($this->header['sign'])) {
//            $this->error('签名验证不能为空', '', 401);
        }
        if (!config('app_debug')) {
//            if ((time() - ceil($this->header['time'] / 1000)) > config('app.app_sign_time')) {
//                $this->error('签名验证超时', '', 401);
//            }
        }
//        if(!$this->checkSign($this->header['sign'], isset($this->header['time'])?$this->header['time']:'', isset($this->header['token'])?$this->header['token']:'')){
//            $this->error('签名验证失败！');
//        }
    }
    protected function checkSign($sign, $time, $token){
        return $sign === md5(config('seller_api_key') . $time . $token);
    }


}